﻿Imports System.IO.Ports
Imports System.Collections.ObjectModel


Partial Class MainWindow
    Private WithEvents _busManager As EIB.BusManager

    Private _lastMessage As Byte() = New Byte() {}

    Private DPT_Types As Dictionary(Of EIBData.EIBDataDPT_Info, List(Of EIBData.EIBDataDPT_Info))
    Private EIS_Types As List(Of EIBData.EIBDataEIS_Info)
    Private Logger As New ObservableCollection(Of EIBBusMessageLogBase)


    Private Sub Connect(port As EIB.ConnectionPort)
        If _busManager Is Nothing OrElse Not _busManager.CanOpenPort(port) Then
            Try
                _busManager = New EIB.BusManager(port)
            Catch ex As Exception
                Disconnect()

                Exit Sub
            End Try
        End If

        If _busManager Is Nothing OrElse Not _busManager.CanOpenPort(port) Then
            Disconnect()

            Exit Sub
        End If

        Dim openResult As Boolean = False

        Select Case port.Category
            Case EIB.ConnectionPortCategory.TP_UART

            Case EIB.ConnectionPortCategory.BCU1_PEI16

            Case EIB.ConnectionPortCategory.BCU2_PEI10_FT12
                openResult = _busManager.Open(port.PortName)
            Case EIB.ConnectionPortCategory.USB

            Case EIB.ConnectionPortCategory.KNXNETIP
                openResult = _busManager.Open("224.0.23.12", 3671) 'aus Einstellungen?
        End Select

        If openResult Then
            ConnectionState = String.Format("{0}: {1}{2}", "Connected", port.ID, If(port.Category = EIB.ConnectionPortCategory.KNXNETIP, String.Format(" @{0}:{1}", "224.0.23.12", 3671), ""))
            IsConnected = True
        Else
            Disconnect()
        End If
    End Sub

    Private Sub Disconnect()
        If _busManager IsNot Nothing Then _busManager.Close()

        ConnectionState = "Disconnected"
        IsConnected = False
    End Sub

    Private Sub _busManager_BusDataReceived(sender As Object, e As EIBData.EventArgs.EIBBusDataUpdatedEventArgs) Handles _busManager.BusDataReceived

    End Sub

    Private Sub _busManager_LogBusData(reason As EIB.Bus.EIBBusAccessLogReason, message As String, data() As Byte) Handles _busManager.LogBusData
        Select Case reason
            Case EIB.Bus.EIBBusAccessLogReason.IncomingMessage, EIB.Bus.EIBBusAccessLogReason.OutgoingMessage
                Dispatcher.Invoke(Sub()
                                      If data.Length > 1 Then
                                          Dim isDublicate As Boolean = IsSameMessage(data, _lastMessage)

                                          'If reason = EIB.Bus.EIBBusAccessLogReason.IncomingMessage Then
                                          Dim FT12type = EIB.Bus.FT12.FT12_FrameBase.GetFrameType(data)

                                          If FT12type = EIB.Bus.FT12.FT12_FrameType.Variable Then
                                              Dim ft12 As New EIB.Bus.FT12.FT12_FrameVariable(data)
                                              Dim MSGtype = EIB.Bus.EIBBusData_FrameBase.GetMessageType(ft12.Data)
                                              Dim msg As Object = Nothing

                                              If MSGtype = EIB.BusData.EIBBusData_EMICode.L_Data_con OrElse
                                                 MSGtype = EIB.BusData.EIBBusData_EMICode.L_Data_ind OrElse
                                                 MSGtype = EIB.BusData.EIBBusData_EMICode.L_Data_req Then

                                                  msg = New EIB.Bus.EIBBusData_FrameLData(ft12.Data)
                                              ElseIf MSGtype = EIB.BusData.EIBBusData_EMICode.L_Busmon_ind Then
                                                  msg = New EIB.Bus.EIBBusData_FrameLBusMonData(ft12.Data)
                                              End If

                                              If msg IsNot Nothing Then
                                                  AddLogEntry(isDublicate, String.Format("{0} {1}", If(reason = EIB.Bus.EIBBusAccessLogReason.IncomingMessage, "-->", "<--"), EIB.Helper.HexConverters.ConvertByteArrayToHexString(data)), data, msg.SourceAddress, msg.DestinationAddress, msg.ACPI, msg.Data)
                                              Else
                                                  AddLogEntry(data, String.Format("{0} {1}", If(reason = EIB.Bus.EIBBusAccessLogReason.IncomingMessage, "-->", "<--"), EIB.Helper.HexConverters.ConvertByteArrayToHexString(data)))
                                              End If
                                          Else
                                              AddLogEntry(data, String.Format("{0} {1}", If(reason = EIB.Bus.EIBBusAccessLogReason.IncomingMessage, "-->", "<--"), EIB.Helper.HexConverters.ConvertByteArrayToHexString(data)))
                                          End If
                                          'End If
                                          _lastMessage = data
                                      Else
                                          'ACK
                                          AddLogEntry(data, String.Format("{0} {1}", If(reason = EIB.Bus.EIBBusAccessLogReason.IncomingMessage, "-->", "<--"), EIB.Helper.HexConverters.ConvertByteArrayToHexString(data)))
                                      End If
                                  End Sub)
            Case EIB.Bus.EIBBusAccessLogReason.Information
                Dispatcher.Invoke(Sub()
                                      AddLogEntry(String.Format("{0} {1}: {2}", "   ", "INFO", message))
                                  End Sub)
            Case EIB.Bus.EIBBusAccessLogReason.Error
                Dispatcher.Invoke(Sub()
                                      AddLogEntry(String.Format("{0} {1}: {2}", "   ", "ERROR", message))
                                  End Sub)
        End Select
    End Sub

    Private Sub AddLogEntry(isDublicate As Boolean, message As String, busdata As Byte(), sourceAddress As EIB.Bus.Addressing.EIBPhysicalAddress, destinationAddress As EIB.Bus.Addressing.EIBAddress, type As EIB.BusData.EIBBusData_FrameACPI_L_Data_Type, value As Byte())
        Dim ble As New EIBBusMessageLogEntry(isDublicate, message, busdata, sourceAddress, destinationAddress, type, value)

        Logger.Add(ble)
    End Sub

    Private Sub AddLogEntry(busdata As Byte(), message As String)
        Dim bli As New EIBBusMessageLogInfo(message, busdata)

        Logger.Add(bli)
    End Sub

    Private Sub AddLogEntry(message As String)
        Dim bli As New EIBBusMessageLogInfo(message)

        Logger.Add(bli)
    End Sub


    Private Sub WriteBusAddress(address As EIB.Bus.Addressing.EIBGroupAddress, value As EIBData.EIS.EIBDataEIS_Base)
        _busManager.WriteGroupAddress(address, value)
    End Sub

    Private Sub WriteBusAddress(address As EIB.Bus.Addressing.EIBGroupAddress, value As EIBData.DPT.EIBDataDPT_Base)
        _busManager.WriteGroupAddress(address, value)
    End Sub

    Private Sub ReadBusAddress(address As EIB.Bus.Addressing.EIBGroupAddress)
        _busManager.ReadGroupAddress(address)
    End Sub

    Private Sub ForceReadBusAddress(address As EIB.Bus.Addressing.EIBGroupAddress)
        _busManager.ForceReadGroupAddress(address)
    End Sub



    Private Function DecodeString(str As String) As String()
        Dim d As String() = New String(str.Length - 1) {}

        For i = 0 To str.Length - 1
            d(i) = AscW(str(i))
        Next

        Return d
    End Function

    Private Function IsSameMessage(data1 As Byte(), data2 As Byte()) As Boolean
        If data1.Length <> data2.Length Then Return False

        For i = 0 To data1.Length - 1
            If data1(i) <> data2(i) Then Return False
        Next

        Return True
    End Function

    




    Private Function GetDecodableEISTypes(DataOctetLength As Byte, Optional sortList As Boolean = False) As List(Of EIBData.EIBDataEIS_Info)
        Dim l As New List(Of EIBData.EIBDataEIS_Info)

        For Each eisi In EIS_Types
            If eisi.EIS_OctetLength = DataOctetLength Then l.Add(eisi)
        Next

        If sortList Then l.Sort(Function(eisi1 As EIBData.EIBDataEIS_Info, eisi2 As EIBData.EIBDataEIS_Info)
                                    Return eisi1.EIS_Name.CompareTo(eisi2.EIS_Name)
                                End Function)

        Return l
    End Function

    Private Function GetDecodeableDPTMainTypes(DataOctetLength As Byte, Optional sortList As Boolean = False) As List(Of EIBData.EIBDataDPT_Info)
        Dim l As New List(Of EIBData.EIBDataDPT_Info)

        For Each dpti In DPT_Types.Keys
            If dpti.DPT_OctetLength = DataOctetLength Then l.Add(dpti)
        Next

        If sortList Then l.Sort(Function(dpti1 As EIBData.EIBDataDPT_Info, dpti2 As EIBData.EIBDataDPT_Info)
                                    Dim x As Byte = dpti1.DPT_Number.Split(".")(0)
                                    Dim y As Byte = dpti2.DPT_Number.Split(".")(0)

                                    Return x.CompareTo(y)
                                End Function)

        Return l
    End Function

    Private Function GetDecodableDPTSubTypes(main As EIBData.EIBDataDPT_Info, Optional sortList As Boolean = False) As List(Of EIBData.EIBDataDPT_Info)
        Dim l As New List(Of EIBData.EIBDataDPT_Info)

        For Each dpti In DPT_Types(main)
            l.Add(dpti)
        Next

        If sortList Then l.Sort(Function(dpti1 As EIBData.EIBDataDPT_Info, dpti2 As EIBData.EIBDataDPT_Info)
                                    Dim x As Byte = dpti1.DPT_Number.Split(".")(1)
                                    Dim y As Byte = dpti2.DPT_Number.Split(".")(1)

                                    Return x.CompareTo(y)
                                End Function)

        Return l
    End Function
End Class